/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = cnaps2.h                                           */
/*  NOTE      =                                                    */
/*  DATE      = 2016/01/11 by songbb                               */
/*******************************************************************/

#ifndef __CNAPS2_H_
#define __CNAPS2_H_

#define APM_CNAPS2_DISABLED 0               //!< CNAPS2开关
#define APM_CNAPS2_DBG 0                    //!< CNAPS2的Debug开关
#define APM_ORA_ENABLE_COLOR_PRINT 1        //!< 是否启用彩色打印

#define APM_CNAPS2_HASH_SIZE 100            //!< CNAPS2模块哈希桶的最大尺寸

#define CNAPS2_IS_FAIL 0
#define CNAPS2_IS_H_V1 1
#define CNAPS2_IS_H_V2 2
#define CNAPS2_IS_U 3

#define CNAPS2_VERSION1 "01"                    //!< 网上支付跨行清算系统报文交换标准
#define CNAPS2_VERSION2 "02"                    //!< 第二代支付系统报文交换标准（不包含其中的网上支付跨行清算系统）
#define CNAPS2_VERSIONID_OFFSET 3               //!< 版本号下标
#define CNAPS2_H_HEADER_LEN 132                 //!< 报文头长度
#define CNAPS2_U_HEADER_LEN 627                 //!< 报文头长度
#define CNAPS2_H_HEADER_BEGIN "{H:"             //!< 报文头的起始标识
#define CNAPS2_U_HEADER_BEGIN "{U:"             //!< 报文头的起始标识
#define CNAPS2_HEADER_END "}\r\n"               //!< 报文头的结束标识
#define CNAPS2_H_HEADER_STRUCT_TYPE_OFFSET 55   //!< 格式类型下标
#define CNAPS2_U_HEADER_STRUCT_TYPE_OFFSET 71   //!< 格式类型下标
#define CNAPS2_HEADER_STRUCT_TYPE_LEN 3         //!< 格式类型长度
#define CNAPS2_H_HEADER_MESG_TYPE_OFFSET 58     //!< 报文类型下标
#define CNAPS2_U_HEADER_MESG_TYPE_OFFSET 76     //!< 报文类型下标
#define CNAPS2_HEADER_MESG_TYPE_LEN 20          //!< 报文类型长度
#define CNAPS2_H_HEADER_MESG_ID_OFFSET 78       //!< 通信级标识号下标
#define CNAPS2_U_HEADER_MESG_ID_OFFSET 96       //!< 通信级标识号下标
#define CNAPS2_HEADER_MESG_ID_LEN 20            //!< 通信级标识号长度
#define CNAPS2_H_HEADER_MESG_REF_ID_OFFSET 98   //!< 通信级参考号下标
#define CNAPS2_U_HEADER_MESG_REF_ID_OFFSET 116  //!< 通信级参考号下标
#define CNAPS2_HEADER_MESG_REF_ID_LEN 20        //!< 通信级参考号长度
#define CNAPS2_H_HEADER_END_OFFSET 129          //!< 报文头的结束标识下标
#define CNAPS2_U_HEADER_END_OFFSET 624          //!< 报文头的结束标识下标
#define CNAPS2_SIGNATURE_BEGIN "{S:"            //!< 数字签名域的起始标识
#define CNAPS2_SIGNATURE_END "}\r\n"            //!< 数字签名域的结束标识
#define CNAPS2_HEADER_MESG_TYPE_CN_LEN 64       //!< 报文类型中文长度

#if APM_ORA_ENABLE_COLOR_PRINT
    #define KRED        "\x1B[0;31m"    //!< ANSI红色
    #define KSALMON     "\x1B[1;31m"    //!< ANSI鲑红色
    #define KGREEN      "\x1B[0;32m"    //!< ANSI绿色
    #define KLIMEGREEN  "\x1B[1;32m"    //!< ANSI青柠色
    #define KYELLOW     "\x1B[0;33m"    //!< ANSI黄色
    #define KORANGE     "\x1B[0;34m"    //!< ANSI橘黄色
    #define KBLUE       "\x1B[1;34m"    //!< ANSI蓝色
    #define KMAGENTA    "\x1B[0;35m"    //!< ANSI洋红色
    #define KPINK       "\x1B[1;35m"    //!< ANSI粉色
    #define KCYAN       "\x1B[0;36m"    //!< ANSI青色
    #define RESET       "\x1B[0m"       //!< ANSI颜色重置
#else
#define KRED        ""
    #define KSALMON     ""
    #define KGREEN      ""
    #define KLIMEGREEN  ""
    #define KYELLOW     ""
    #define KORANGE     ""
    #define KBLUE       ""
    #define KMAGENTA    ""
    #define KPINK       ""
    #define KCYAN       ""
    #define RESET       ""
#endif


#if APM_CNAPS2_DBG
#define PRINT_HEX_STRING(a,b,c) (printf("[%s, Line:%u, %s()] ",\
                            __FILE__,__LINE__,__func__),\
                            printf("%s", KCYAN),\
                            printf(a":["),__print_hex_string(b,c),printf("]\n"),\
                            printf("%s", RESET))
#define CNAPS2_PRINT(...) printf(__VA_ARGS__)
#define CNAPS2_PRINT_DETAIL(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(__VA_ARGS__))
#define CNAPS2_PRINT_DBG(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf("%s", KGREEN),\
                        printf(" "__VA_ARGS__),\
                        printf("%s", RESET))
#define CNAPS2_PRINT_FATAL(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf("%s", KORANGE),\
                        printf(" "__VA_ARGS__),\
                        printf("%s", RESET))
#define CNAPS2_PRINT_EMERG(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf("%s", KRED),\
                        printf(" "__VA_ARGS__),\
                        printf("%s", RESET))
#define CNAPS2_PRINT_ALERT(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf("%s", KSALMON),\
                        printf(" "__VA_ARGS__),\
                        printf("%s", RESET))
#define CNAPS2_PRINT_CRIT(...) (printf("[%s, Line:%u, %s()]",\
                            __FILE__,__LINE__,__func__),\
                            printf("%s", KMAGENTA),\
                            printf(" "__VA_ARGS__),\
                            printf("%s", RESET))
#define CNAPS2_PRINT_ERR(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf("%s", KPINK),\
                        printf(" "__VA_ARGS__),\
                        printf("%s", RESET))
#define CNAPS2_PRINT_WARN(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf("%s", KYELLOW),\
                        printf(" "__VA_ARGS__),\
                        printf("%s", RESET))
#define CNAPS2_PRINT_NOTICE(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf("%s", KLIMEGREEN),\
                        printf(" "__VA_ARGS__),\
                        printf("%s", RESET))
#define CNAPS2_PRINT_INFO(...) (printf("[%s, Line:%u, %s()]",\
                            __FILE__,__LINE__,__func__),\
                            printf("%s", KBLUE),\
                            printf(" "__VA_ARGS__),\
                            printf("%s", RESET))
#define CNAPS2_PRINT_TIMEVAL(a,b) (printf("[%s, Line:%u, %s()]",\
                            __FILE__,__LINE__,__func__),\
                            printf("%s", KGREEN),\
                            printf(" %s", a), \
                             cnaps2_print_timeval(b),\
                             printf("%s", RESET))
#else
#define PRINT_HEX_STRING(a,b,c)
#define CNAPS2_PRINT(...)
#define CNAPS2_PRINT_DETAIL(...)
#define CNAPS2_PRINT_DBG(...)
#define CNAPS2_PRINT_FATAL(...)
#define CNAPS2_PRINT_EMERG(...)
#define CNAPS2_PRINT_ALERT(...)
#define CNAPS2_PRINT_CRIT(...)
#define CNAPS2_PRINT_ERR(...)
#define CNAPS2_PRINT_WARN(...)
#define CNAPS2_PRINT_NOTICE(...)
#define CNAPS2_PRINT_INFO(...)
#define CNAPS2_PRINT_TIMEVAL(a,b)
#endif

#define CNAPS2_MALLOCK_ERR CNAPS2_PRINT_EMERG("can not malloc memory\n"); \
                              FRLOG_ERROR_DETAIL("can not malloc memory");  //!< malloc执行出错记录

typedef struct __st_L7_cnaps2_stmt
{
    int i_is_req;
    Frlist_header *p_report_comm;        //!< 用于临时存储report的公共部分数据
    Frlist_header *p_report_req;         //!< 用于临时存储report的请求部分数据
    long long ll_req_end_timestamp;      //!< 请求的结束时间戳
    unsigned int ui_src_ip;              //!< 记录请求的源地址
    unsigned short us_src_port;          //!< 记录请求的源端口
    unsigned int ui_dst_ip;              //!< 记录请求的目的地址
    unsigned short us_dst_port;          //!< 记录请求的目的端口
    char *p_req_mesg_type;               //!< 交易类型
    char *p_req_mesg_type_cn;            //!< 交易类型中文含义
    char *p_req_mesg_id;
    char *p_req_mesg_ref_id;

    long long ll_resp_start_timestamp;
    long long ll_resp_end_timestamp;
    long long ll_resp_download_time;
    long long ll_resp_data_bytes;
    char *p_resp_mesg_type;
    char *p_resp_mesg_type_cn;
    char *p_resp_mesg_id;
    char *p_resp_mesg_ref_id;
    int i_resp_code_short;
    char *p_resp_code;
    char *p_resp_codestring;
    char *p_resp_mq_message;

    long l_stmt_time;
} L7_cnaps2_stmt;

void cnaps2_print_timeval(struct timeval st_timestamp);

void __print_hex_string(char *p_buff, int i_len);

/*!
 * 对arr_mesg_type_maps进行快速排列
 *
 * \param i_start  (开始位置)
 * \param i_right (结束位置)
 *
 * \return void
 *
 */
void cnaps2_mesg_type_quicksort(int i_start
                                , int i_right);

/*!
 * 对arr_mesg_resp进行快速排列
 *
 * \param i_start  (开始位置)
 * \param i_right (结束位置)
 *
 * \return void
 *
 */
void cnaps2_mesg_resp_quicksort(int i_start
                                , int i_right);

void cnaps2_stmt_node_free(Frlist_node *p_st_node);

/*!
 * CNAPS2协议解析
 *
 * \param p_st_conn         (ct)
 * \param p_st_report_data  (数据上报结构体)
 * \param p_st_data_req     (data_req)
 * \param p_st_hash_report  (hash report)
 *
 * \return 0  失败\n
 *         1  成功
 *         2  表明需要在外面丢弃当前生成的Frreport_data
 *
 * \note 需要在外面丢弃当前生成的Frreport_data
 */
int cnaps2_parse(Conntrack *p_st_conn
                , Frreport_data *p_st_report_data
                , Frhash_header *p_st_hash_report
                , int i_is_mq_req);

#endif
